package com.tjut.core.utils;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

public class OkhttpUtils {

    static OkHttpClient HTTP_CLIENT;

    public static void build(CookieJar cookieJar) {
        HTTP_CLIENT = new OkHttpClient.Builder()
                .followRedirects(false)
                .cookieJar(cookieJar)
                .build();
    }

    public static final MediaType JSON
            = MediaType.get("application/json; charset=utf-8");
    public static final MediaType FORM = MediaType.parse("application/x-www-form-urlencoded");

    private static String getEncodedGETUrl(String url, Map<String, String> params) {
        StringBuilder sb = new StringBuilder(url);
        if (!params.isEmpty()) {
            sb.append('?');
            params.forEach((k, v) -> {
                try {
                    sb.append(URLEncoder.encode(k, "UTF-8"));
                    sb.append('=');
                    sb.append(URLEncoder.encode(v, "UTF-8"));
                    sb.append('&');
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            });
            //删除多余的&
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }


    private static Request getRequest(String url) {
        return new Request.Builder()
                .get()
                .url(url)
                .build();
    }

    private static Request getRequest(String url, String json) {
        RequestBody requestBody = RequestBody.create(JSON, json);
        return new Request.Builder()
                .post(requestBody)
                .url(url)
                .build();
    }

    private static Request getRequest(String url, FormBody formBody) {
        return new Request.Builder()
                .post(formBody)
                .url(url)
                .build();
    }

    /**
     * 根据传入的url，获取set-cookie
     *
     * @param url
     * @param
     * @return 可能存在的重定向地址
     */
    public static String get(String url) {
        Request request = getRequest(url);
        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            //判断是否是重定向
            if (response.isRedirect()) {
                return response.header("Location");
            }
            return Objects.requireNonNull(response.body()).string();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String get(String url, Map params) {
        if (params == null) return get(url);
        url = getEncodedGETUrl(url, params);
        return get(url);


    }

    public static <T> T get(String url, Class<T> clz) {
        return parse(get(url), clz);
    }


    private static FormBody getParams(Map<String, String> params) {
        FormBody.Builder formBuilder = new FormBody.Builder();
        params.forEach(formBuilder::add);
        return formBuilder.build();
    }

    public static String post(String url, Map<String, String> params) {
        Request request = getRequest(url, getParams(params));
        return synchronizedCall(request);
    }

    public static String post(String url, String json) {
        Request request = getRequest(url, json);
        return synchronizedCall(request);
    }

    public static <T> T post(String url, String json, Class<T> clz) {
        return parse(post(url, json), clz);
    }

    public static String put(String url, String json) {
        RequestBody body = RequestBody.create(JSON, json);

        Request request = new Request.Builder()
                .url(url)
                .put(body)
                .build();

        return synchronizedCall(request);
    }

    public static String put(String url) {
        return put(url, "");
    }


    public static <T> T put(String url, String json, Class<T> clz) {
        return parse(put(url, json), clz);
    }


    public static String delete(String url, String json) {
        RequestBody body = RequestBody.create(JSON, json);

        Request request = new Request.Builder()
                .url(url)
                .delete(body)
                .build();
        return synchronizedCall(request);
    }

    public static String delete(String url) {
        return delete(url, "");
    }

    public static <T> T delete(String url, Class<T> clz) {
        return parse(
                delete(url, ""),
                clz
        );
    }

    public static <T> T delete(String url, String json, Class<T> clz) {
        return parse(delete(url, json), clz);
    }

    private static String synchronizedCall(Request request) {
        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            if (response.isRedirect()) {
                return response.header("Location");
            }
            ResponseBody body = response.body();
            return Objects.requireNonNull(body).string();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static <T> T synchronizedCall(Request request, Class<T> clz) {
        return parse(synchronizedCall(request), clz);
    }

    public static <T> T parse(String json, Class<T> clz) {
        return JSONObject.parseObject(json, clz);
    }

}
